#ifndef __UTILS_HPP__
#define __UTILS_HPP__

#include <cuda_runtime.h>
#include <stdarg.h>
#include <system_error>

#define CUDA_CHECK(call) __cudaCheck(call, __FILE__, __LINE__)
#define LAST_KERNEL_CHECK(call) __kernelCheck(__FILE__, __LINE__)
#define LOG(...) __log_info(__VA_ARGS__)

#define BLOCKSIZE 16

static void __cudaCheck(cudaError_t err, const char *file, const int line) {
  if (err != cudaSuccess) {
    printf("ERROR: %s:%d, ", file, line);
    printf("CODE:%s, DETAIL:%s\n", cudaGetErrorName(err),
           cudaGetErrorString(err));
    exit(1);
  }
}

static void __kernelCheck(const char *file, const int line) {
  cudaError_t err = cudaPeekAtLastError();
  if (err != cudaSuccess) {
    printf("ERROR: %s:%d, ", file, line);
    printf("CODE:%s, DETAIL:%s\n", cudaGetErrorName(err),
           cudaGetErrorString(err));
    exit(1);
  }
}

// 使用变参进行LOG的打印。比较推荐的打印log的写法
static void __log_info(const char *format, ...) {
  char msg[1000];
  va_list args;
  va_start(args, format);

  vsnprintf(msg, sizeof(msg), format, args);

  fprintf(stdout, "%s\n", msg);
  va_end(args);
}

void initMatrix(float *data, int size, int low, int high, int seed);
void printMat(float *data, int size);
void compareMat(float *h_data, float *d_data, int size);

#endif //__UTILS_HPP__//
